#pragma once

#include <QtCore/QtGlobal>
#include <QObject>
#include <QList>
#include <QStringList>
#include <QMap>
#include <QUrl>
#include <QFileSystemWatcher>
#include <QTimer>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include "mediaitem.h"

class Keyword {
public:
    Keyword(const QString & keyword) : m_keyword(keyword) {}

    QString keyword() { return m_keyword; }

    void setParent(QWeakPointer<Keyword> parent);
    QWeakPointer<Keyword> parent() { return m_parent; }

private:
    QString m_keyword;
    QWeakPointer<Keyword> m_parent;
};

class Library : public QThread {
    Q_OBJECT
public:
    Library();
    ~Library();

    void setRootPath(const QString & path);
    QString rootPath();
    bool scanning();
    QList<QSharedPointer<MediaItem> > items();
    QStringList folders();
    QSet<QSharedPointer<MediaItem> > set(QSharedPointer<MediaItem> item);
    QList<QSharedPointer<Keyword> > keywords() { return m_keywords; }
    void collectKeywords(QSharedPointer<MediaItem> item);

signals:
    void added(QSharedPointer<MediaItem> item);
    void removed(QSharedPointer<MediaItem> item);
    void updated(QSharedPointer<MediaItem> item);
    void status(const QString & str);
    void keywordsChanged();

public slots:
    // update library
    void update();

    // update part of the library
    void update(QString path);

    // move the provided files (from the library) to target_folder
    void move(const QList<QUrl> & urls, const QString & target_folder);

    // add file to library (without copying or moving the file)
    void add(const QString & filename);

    // update meta data
    void update(QSharedPointer<MediaItem> item);

    // remove item from library without deleting the file
    void remove(QSharedPointer<MediaItem> item);

    // remove item from library and delete file
    void erase(QSharedPointer<MediaItem> item);

protected:
    virtual void run();

private:
    void add(QSharedPointer<MediaItem> item);
    void modified(QSharedPointer<MediaItem> item);
    void deleteEmptyDirectories(QString path, int mindepth);
    QString group(QSharedPointer<MediaItem> item);

    bool m_quit;
    QMutex m_mutex;
    QWaitCondition m_cond;

    QString m_root;
    QMap<QString, QSharedPointer<MediaItem> > m_items;
    QStringList m_queue;

    int m_added, m_updated, m_removed, m_dirs;

    QStringList m_changedPaths;

    QMap<QString, QSet<QSharedPointer<MediaItem> > > m_itemgroups;
    QMap<QSharedPointer<MediaItem>, QString> m_group;

    QList<QSharedPointer<Keyword> > m_keywords;
};
